home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / cl_ents.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-27  |  36.1 KB  |  1,398 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // cl_ents.c -- entity parsing and management
  21.  
  22. #include "client.h"
  23.  
  24.  
  25. extern    struct model_s    *cl_mod_powerscreen;
  26.  
  27. /*
  28. =========================================================================
  29.  
  30. FRAME PARSING
  31.  
  32. =========================================================================
  33. */
  34.  
  35. /*
  36. =================
  37. CL_ParseEntityBits
  38.  
  39. Returns the entity number and the header bits
  40. =================
  41. */
  42. int    bitcounts[32];    /// just for protocol profiling
  43. int CL_ParseEntityBits (unsigned *bits)
  44. {
  45.     unsigned    b, total;
  46.     int            i;
  47.     int            number;
  48.  
  49.     total = MSG_ReadByte (&net_message);
  50.     if (total & U_MOREBITS1)
  51.     {
  52.         b = MSG_ReadByte (&net_message);
  53.         total |= b<<8;
  54.     }
  55.     if (total & U_MOREBITS2)
  56.     {
  57.         b = MSG_ReadByte (&net_message);
  58.         total |= b<<16;
  59.     }
  60.     if (total & U_MOREBITS3)
  61.     {
  62.         b = MSG_ReadByte (&net_message);
  63.         total |= b<<24;
  64.     }
  65.  
  66.     // count the bits for net profiling
  67.     for (i=0 ; i<32 ; i++)
  68.         if (total&(1<<i))
  69.             bitcounts[i]++;
  70.  
  71.     if (total & U_NUMBER16)
  72.         number = MSG_ReadShort (&net_message);
  73.     else
  74.         number = MSG_ReadByte (&net_message);
  75.  
  76.     *bits = total;
  77.  
  78.     return number;
  79. }
  80.  
  81. /*
  82. ==================
  83. CL_ParseDelta
  84.  
  85. Can go from either a baseline or a previous packet_entity
  86. ==================
  87. */
  88. void CL_ParseDelta (entity_state_t *from, entity_state_t *to, int number, int bits)
  89. {
  90.     // set everything to the state we are delta'ing from
  91.     *to = *from;
  92.  
  93.     VectorCopy (from->origin, to->old_origin);
  94.     to->number = number;
  95.  
  96.     if (bits & U_MODEL)
  97.         to->modelindex = MSG_ReadByte (&net_message);
  98.     if (bits & U_MODEL2)
  99.         to->modelindex2 = MSG_ReadByte (&net_message);
  100.     if (bits & U_MODEL3)
  101.         to->modelindex3 = MSG_ReadByte (&net_message);
  102.     if (bits & U_MODEL4)
  103.         to->modelindex4 = MSG_ReadByte (&net_message);
  104.         
  105.     if (bits & U_FRAME8)
  106.         to->frame = MSG_ReadByte (&net_message);
  107.     if (bits & U_FRAME16)
  108.         to->frame = MSG_ReadShort (&net_message);
  109.  
  110.     if ((bits & U_SKIN8) && (bits & U_SKIN16))        //used for laser colors
  111.         to->skinnum = MSG_ReadLong(&net_message);
  112.     else if (bits & U_SKIN8)
  113.         to->skinnum = MSG_ReadByte(&net_message);
  114.     else if (bits & U_SKIN16)
  115.         to->skinnum = MSG_ReadShort(&net_message);
  116.  
  117.     if ( (bits & (U_EFFECTS8|U_EFFECTS16)) == (U_EFFECTS8|U_EFFECTS16) )
  118.         to->effects = MSG_ReadLong(&net_message);
  119.     else if (bits & U_EFFECTS8)
  120.         to->effects = MSG_ReadByte(&net_message);
  121.     else if (bits & U_EFFECTS16)
  122.         to->effects = MSG_ReadShort(&net_message);
  123.  
  124.     if ( (bits & (U_RENDERFX8|U_RENDERFX16)) == (U_RENDERFX8|U_RENDERFX16) )
  125.         to->renderfx = MSG_ReadLong(&net_message);
  126.     else if (bits & U_RENDERFX8)
  127.         to->renderfx = MSG_ReadByte(&net_message);
  128.     else if (bits & U_RENDERFX16)
  129.         to->renderfx = MSG_ReadShort(&net_message);
  130.  
  131.     if (bits & U_ORIGIN1)
  132.         to->origin[0] = MSG_ReadCoord (&net_message);
  133.     if (bits & U_ORIGIN2)
  134.         to->origin[1] = MSG_ReadCoord (&net_message);
  135.     if (bits & U_ORIGIN3)
  136.         to->origin[2] = MSG_ReadCoord (&net_message);
  137.         
  138.     if (bits & U_ANGLE1)
  139.         to->angles[0] = MSG_ReadAngle(&net_message);
  140.     if (bits & U_ANGLE2)
  141.         to->angles[1] = MSG_ReadAngle(&net_message);
  142.     if (bits & U_ANGLE3)
  143.         to->angles[2] = MSG_ReadAngle(&net_message);
  144.  
  145.     if (bits & U_OLDORIGIN)
  146.         MSG_ReadPos (&net_message, to->old_origin);
  147.  
  148.     if (bits & U_SOUND)
  149.         to->sound = MSG_ReadByte (&net_message);
  150.  
  151.     if (bits & U_EVENT)
  152.         to->event = MSG_ReadByte (&net_message);
  153.     else
  154.         to->event = 0;
  155.  
  156.     if (bits & U_SOLID)
  157.         to->solid = MSG_ReadShort (&net_message);
  158. }
  159.  
  160. /*
  161. ==================
  162. CL_DeltaEntity
  163.  
  164. Parses deltas from the given base and adds the resulting entity
  165. to the current frame
  166. ==================
  167. */
  168. void CL_DeltaEntity (frame_t *frame, int newnum, entity_state_t *old, int bits)
  169. {
  170.     centity_t    *ent;
  171.     entity_state_t    *state;
  172.  
  173.     ent = &cl_entities[newnum];
  174.  
  175.     state = &cl_parse_entities[cl.parse_entities & (MAX_PARSE_ENTITIES-1)];
  176.     cl.parse_entities++;
  177.     frame->num_entities++;
  178.  
  179.     CL_ParseDelta (old, state, newnum, bits);
  180.  
  181.     // some data changes will force no lerping
  182.     if (state->modelindex != ent->current.modelindex
  183.         || state->modelindex2 != ent->current.modelindex2
  184.         || state->modelindex3 != ent->current.modelindex3
  185.         || state->modelindex4 != ent->current.modelindex4
  186.         || abs(state->origin[0] - ent->current.origin[0]) > 512
  187.         || abs(state->origin[1] - ent->current.origin[1]) > 512
  188.         || abs(state->origin[2] - ent->current.origin[2]) > 512
  189.         || state->event == EV_PLAYER_TELEPORT
  190.         || state->event == EV_OTHER_TELEPORT
  191.         )
  192.     {
  193.         ent->serverframe = -99;
  194.     }
  195.  
  196.     if (ent->serverframe != cl.frame.serverframe - 1)
  197.     {    // wasn't in last update, so initialize some things
  198.         ent->trailcount = 1024;        // for diminishing rocket / grenade trails
  199.         // duplicate the current state so lerping doesn't hurt anything
  200.         ent->prev = *state;
  201.         if (state->event == EV_OTHER_TELEPORT)
  202.         {
  203.             VectorCopy (state->origin, ent->prev.origin);
  204.             VectorCopy (state->origin, ent->lerp_origin);
  205.         }
  206.         else
  207.         {
  208.             VectorCopy (state->old_origin, ent->prev.origin);
  209.             VectorCopy (state->old_origin, ent->lerp_origin);
  210.         }
  211.     }
  212.     else
  213.     {    // shuffle the last state to previous
  214.         ent->prev = ent->current;
  215.     }
  216.  
  217.     ent->serverframe = cl.frame.serverframe;
  218.     ent->current = *state;
  219. }
  220.  
  221. /*
  222. ==================
  223. CL_ParsePacketEntities
  224.  
  225. An svc_packetentities has just been parsed, deal with the
  226. rest of the data stream.
  227. ==================
  228. */
  229. void CL_ParsePacketEntities (frame_t *oldframe, frame_t *newframe)
  230. {
  231.     int            newnum;
  232.     int            bits;
  233.     entity_state_t    *oldstate;
  234.     int            oldindex, oldnum;
  235.  
  236.     newframe->parse_entities = cl.parse_entities;
  237.     newframe->num_entities = 0;
  238.  
  239.     // delta from the entities present in oldframe
  240.     oldindex = 0;
  241.     if (!oldframe)
  242.         oldnum = 99999;
  243.     else
  244.     {
  245.         if (oldindex >= oldframe->num_entities)
  246.             oldnum = 99999;
  247.         else
  248.         {
  249.             oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
  250.             oldnum = oldstate->number;
  251.         }
  252.     }
  253.  
  254.     while (1)
  255.     {
  256.         newnum = CL_ParseEntityBits (&bits);
  257.         if (newnum >= MAX_EDICTS)
  258.             Com_Error (ERR_DROP,"CL_ParsePacketEntities: bad number:%i", newnum);
  259.  
  260.         if (net_message.readcount > net_message.cursize)
  261.             Com_Error (ERR_DROP,"CL_ParsePacketEntities: end of message");
  262.  
  263.         if (!newnum)
  264.             break;
  265.  
  266.         while (oldnum < newnum)
  267.         {    // one or more entities from the old packet are unchanged
  268.             if (cl_shownet->value == 3)
  269.                 Com_Printf ("   unchanged: %i\n", oldnum);
  270.             CL_DeltaEntity (newframe, oldnum, oldstate, 0);
  271.             
  272.             oldindex++;
  273.  
  274.             if (oldindex >= oldframe->num_entities)
  275.                 oldnum = 99999;
  276.             else
  277.             {
  278.                 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
  279.                 oldnum = oldstate->number;
  280.             }
  281.         }
  282.  
  283.         if (bits & U_REMOVE)
  284.         {    // the entity present in oldframe is not in the current frame
  285.             if (cl_shownet->value == 3)
  286.                 Com_Printf ("   remove: %i\n", newnum);
  287.             if (oldnum != newnum)
  288.                 Com_Printf ("U_REMOVE: oldnum != newnum\n");
  289.  
  290.             oldindex++;
  291.  
  292.             if (oldindex >= oldframe->num_entities)
  293.                 oldnum = 99999;
  294.             else
  295.             {
  296.                 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
  297.                 oldnum = oldstate->number;
  298.             }
  299.             continue;
  300.         }
  301.  
  302.         if (oldnum == newnum)
  303.         {    // delta from previous state
  304.             if (cl_shownet->value == 3)
  305.                 Com_Printf ("   delta: %i\n", newnum);
  306.             CL_DeltaEntity (newframe, newnum, oldstate, bits);
  307.  
  308.             oldindex++;
  309.  
  310.             if (oldindex >= oldframe->num_entities)
  311.                 oldnum = 99999;
  312.             else
  313.             {
  314.                 oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
  315.                 oldnum = oldstate->number;
  316.             }
  317.             continue;
  318.         }
  319.  
  320.         if (oldnum > newnum)
  321.         {    // delta from baseline
  322.             if (cl_shownet->value == 3)
  323.                 Com_Printf ("   baseline: %i\n", newnum);
  324.             CL_DeltaEntity (newframe, newnum, &cl_entities[newnum].baseline, bits);
  325.             continue;
  326.         }
  327.  
  328.     }
  329.  
  330.     // any remaining entities in the old frame are copied over
  331.     while (oldnum != 99999)
  332.     {    // one or more entities from the old packet are unchanged
  333.         if (cl_shownet->value == 3)
  334.             Com_Printf ("   unchanged: %i\n", oldnum);
  335.         CL_DeltaEntity (newframe, oldnum, oldstate, 0);
  336.         
  337.         oldindex++;
  338.  
  339.         if (oldindex >= oldframe->num_entities)
  340.             oldnum = 99999;
  341.         else
  342.         {
  343.             oldstate = &cl_parse_entities[(oldframe->parse_entities+oldindex) & (MAX_PARSE_ENTITIES-1)];
  344.             oldnum = oldstate->number;
  345.         }
  346.     }
  347. }
  348.  
  349.  
  350.  
  351. /*
  352. ===================
  353. CL_ParsePlayerstate
  354. ===================
  355. */
  356. void CL_ParsePlayerstate (frame_t *oldframe, frame_t *newframe)
  357. {
  358.     int            flags;
  359.     player_state_t    *state;
  360.     int            i;
  361.     int            statbits;
  362.  
  363.     state = &newframe->playerstate;
  364.  
  365.     // clear to old value before delta parsing
  366.     if (oldframe)
  367.         *state = oldframe->playerstate;
  368.     else
  369.         memset (state, 0, sizeof(*state));
  370.  
  371.     flags = MSG_ReadShort (&net_message);
  372.  
  373.     //
  374.     // parse the pmove_state_t
  375.     //
  376.     if (flags & PS_M_TYPE)
  377.         state->pmove.pm_type = MSG_ReadByte (&net_message);
  378.  
  379.     if (flags & PS_M_ORIGIN)
  380.     {
  381.         state->pmove.origin[0] = MSG_ReadShort (&net_message);
  382.         state->pmove.origin[1] = MSG_ReadShort (&net_message);
  383.         state->pmove.origin[2] = MSG_ReadShort (&net_message);
  384.     }
  385.  
  386.     if (flags & PS_M_VELOCITY)
  387.     {
  388.         state->pmove.velocity[0] = MSG_ReadShort (&net_message);
  389.         state->pmove.velocity[1] = MSG_ReadShort (&net_message);
  390.         state->pmove.velocity[2] = MSG_ReadShort (&net_message);
  391.     }
  392.  
  393.     if (flags & PS_M_TIME)
  394.         state->pmove.pm_time = MSG_ReadByte (&net_message);
  395.  
  396.     if (flags & PS_M_FLAGS)
  397.         state->pmove.pm_flags = MSG_ReadByte (&net_message);
  398.  
  399.     if (flags & PS_M_GRAVITY)
  400.         state->pmove.gravity = MSG_ReadShort (&net_message);
  401.  
  402.     if (flags & PS_M_DELTA_ANGLES)
  403.     {
  404.         state->pmove.delta_angles[0] = MSG_ReadShort (&net_message);
  405.         state->pmove.delta_angles[1] = MSG_ReadShort (&net_message);
  406.         state->pmove.delta_angles[2] = MSG_ReadShort (&net_message);
  407.     }
  408.  
  409.     if (cl.attractloop)
  410.         state->pmove.pm_type = PM_FREEZE;        // demo playback
  411.  
  412.     //
  413.     // parse the rest of the player_state_t
  414.     //
  415.     if (flags & PS_VIEWOFFSET)
  416.     {
  417.         state->viewoffset[0] = MSG_ReadChar (&net_message) * 0.25;
  418.         state->viewoffset[1] = MSG_ReadChar (&net_message) * 0.25;
  419.         state->viewoffset[2] = MSG_ReadChar (&net_message) * 0.25;
  420.     }
  421.  
  422.     if (flags & PS_VIEWANGLES)
  423.     {
  424.         state->viewangles[0] = MSG_ReadAngle16 (&net_message);
  425.         state->viewangles[1] = MSG_ReadAngle16 (&net_message);
  426.         state->viewangles[2] = MSG_ReadAngle16 (&net_message);
  427.     }
  428.  
  429.     if (flags & PS_KICKANGLES)
  430.     {
  431.         state->kick_angles[0] = MSG_ReadChar (&net_message) * 0.25;
  432.         state->kick_angles[1] = MSG_ReadChar (&net_message) * 0.25;
  433.         state->kick_angles[2] = MSG_ReadChar (&net_message) * 0.25;
  434.     }
  435.  
  436.     if (flags & PS_WEAPONINDEX)
  437.     {
  438.         state->gunindex = MSG_ReadByte (&net_message);
  439.     }
  440.  
  441.     if (flags & PS_WEAPONFRAME)
  442.     {
  443.         state->gunframe = MSG_ReadByte (&net_message);
  444.         state->gunoffset[0] = MSG_ReadChar (&net_message)*0.25;
  445.         state->gunoffset[1] = MSG_ReadChar (&net_message)*0.25;
  446.         state->gunoffset[2] = MSG_ReadChar (&net_message)*0.25;
  447.         state->gunangles[0] = MSG_ReadChar (&net_message)*0.25;
  448.         state->gunangles[1] = MSG_ReadChar (&net_message)*0.25;
  449.         state->gunangles[2] = MSG_ReadChar (&net_message)*0.25;
  450.     }
  451.  
  452.     if (flags & PS_BLEND)
  453.     {
  454.         state->blend[0] = MSG_ReadByte (&net_message)/255.0;
  455.         state->blend[1] = MSG_ReadByte (&net_message)/255.0;
  456.         state->blend[2] = MSG_ReadByte (&net_message)/255.0;
  457.         state->blend[3] = MSG_ReadByte (&net_message)/255.0;
  458.     }
  459.  
  460.     if (flags & PS_FOV)
  461.         state->fov = MSG_ReadByte (&net_message);
  462.  
  463.     if (flags & PS_RDFLAGS)
  464.         state->rdflags = MSG_ReadByte (&net_message);
  465.  
  466.     // parse stats
  467.     statbits = MSG_ReadLong (&net_message);
  468.     for (i=0 ; i<MAX_STATS ; i++)
  469.         if (statbits & (1<<i) )
  470.             state->stats[i] = MSG_ReadShort(&net_message);
  471. }
  472.  
  473.  
  474. /*
  475. ==================
  476. CL_FireEntityEvents
  477.  
  478. ==================
  479. */
  480. void CL_FireEntityEvents (frame_t *frame)
  481. {
  482.     entity_state_t        *s1;
  483.     int                    pnum, num;
  484.  
  485.     for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
  486.     {
  487.         num = (frame->parse_entities + pnum)&(MAX_PARSE_ENTITIES-1);
  488.         s1 = &cl_parse_entities[num];
  489.         if (s1->event)
  490.             CL_EntityEvent (s1);
  491.  
  492.         // EF_TELEPORTER acts like an event, but is not cleared each frame
  493.         if (s1->effects & EF_TELEPORTER)
  494.             CL_TeleporterParticles (s1);
  495.     }
  496. }
  497.  
  498.  
  499. /*
  500. ================
  501. CL_ParseFrame
  502. ================
  503. */
  504. void CL_ParseFrame (void)
  505. {
  506.     int            cmd;
  507.     int            len;
  508.     frame_t        *old;
  509.  
  510.     memset (&cl.frame, 0, sizeof(cl.frame));
  511.  
  512.     cl.frame.serverframe = MSG_ReadLong (&net_message);
  513.     cl.frame.deltaframe = MSG_ReadLong (&net_message);
  514.     cl.frame.servertime = cl.frame.serverframe*100;
  515.  
  516.     // BIG HACK to let old demos continue to work
  517.     if (cls.serverProtocol != 26)
  518.         cl.surpressCount = MSG_ReadByte (&net_message);
  519.  
  520.     if (cl_shownet->value == 3)
  521.         Com_Printf ("   frame:%i  delta:%i\n", cl.frame.serverframe,
  522.         cl.frame.deltaframe);
  523.  
  524.     // If the frame is delta compressed from data that we
  525.     // no longer have available, we must suck up the rest of
  526.     // the frame, but not use it, then ask for a non-compressed
  527.     // message 
  528.     if (cl.frame.deltaframe <= 0)
  529.     {
  530.         cl.frame.valid = true;        // uncompressed frame
  531.         old = NULL;
  532.         cls.demowaiting = false;    // we can start recording now
  533.     }
  534.     else
  535.     {
  536.         old = &cl.frames[cl.frame.deltaframe & UPDATE_MASK];
  537.         if (!old->valid)
  538.         {    // should never happen
  539.             Com_Printf ("Delta from invalid frame (not supposed to happen!).\n");
  540.         }
  541.         if (old->serverframe != cl.frame.deltaframe)
  542.         {    // The frame that the server did the delta from
  543.             // is too old, so we can't reconstruct it properly.
  544.             Com_Printf ("Delta frame too old.\n");
  545.         }
  546.         else if (cl.parse_entities - old->parse_entities > MAX_PARSE_ENTITIES-128)
  547.         {
  548.             Com_Printf ("Delta parse_entities too old.\n");
  549.         }
  550.         else
  551.             cl.frame.valid = true;    // valid delta parse
  552.     }
  553.  
  554.     // clamp time 
  555.     if (cl.time > cl.frame.servertime)
  556.         cl.time = cl.frame.servertime;
  557.     else if (cl.time < cl.frame.servertime - 100)
  558.         cl.time = cl.frame.servertime - 100;
  559.  
  560.     // read areabits
  561.     len = MSG_ReadByte (&net_message);
  562.     MSG_ReadData (&net_message, &cl.frame.areabits, len);
  563.  
  564.     // read playerinfo
  565.     cmd = MSG_ReadByte (&net_message);
  566.     SHOWNET(svc_strings[cmd]);
  567.     if (cmd != svc_playerinfo)
  568.         Com_Error (ERR_DROP, "CL_ParseFrame: not playerinfo");
  569.     CL_ParsePlayerstate (old, &cl.frame);
  570.  
  571.     // read packet entities
  572.     cmd = MSG_ReadByte (&net_message);
  573.     SHOWNET(svc_strings[cmd]);
  574.     if (cmd != svc_packetentities)
  575.         Com_Error (ERR_DROP, "CL_ParseFrame: not packetentities");
  576.     CL_ParsePacketEntities (old, &cl.frame);
  577.  
  578.     // save the frame off in the backup array for later delta comparisons
  579.     cl.frames[cl.frame.serverframe & UPDATE_MASK] = cl.frame;
  580.  
  581.     if (cl.frame.valid)
  582.     {
  583.         // getting a valid frame message ends the connection process
  584.         if (cls.state != ca_active)
  585.         {
  586.             cls.state = ca_active;
  587.             cl.force_refdef = true;
  588.             cl.predicted_origin[0] = cl.frame.playerstate.pmove.origin[0]*0.125;
  589.             cl.predicted_origin[1] = cl.frame.playerstate.pmove.origin[1]*0.125;
  590.             cl.predicted_origin[2] = cl.frame.playerstate.pmove.origin[2]*0.125;
  591.             VectorCopy (cl.frame.playerstate.viewangles, cl.predicted_angles);
  592.             if (cls.disable_servercount != cl.servercount
  593.                 && cl.refresh_prepped)
  594.                 SCR_EndLoadingPlaque ();    // get rid of loading plaque
  595.         }
  596.         cl.sound_prepped = true;    // can start mixing ambient sounds
  597.     
  598.         // fire entity events
  599.         CL_FireEntityEvents (&cl.frame);
  600.         CL_CheckPredictionError ();
  601.     }
  602. }
  603.  
  604. /*
  605. ==========================================================================
  606.  
  607. INTERPOLATE BETWEEN FRAMES TO GET RENDERING PARMS
  608.  
  609. ==========================================================================
  610. */
  611.  
  612. struct model_s *S_RegisterSexedModel (entity_state_t *ent, char *base)
  613. {
  614.     int                n;
  615.     char            *p;
  616.     struct model_s    *mdl;
  617.     char            model[MAX_QPATH];
  618.     char            buffer[MAX_QPATH];
  619.  
  620.     // determine what model the client is using
  621.     model[0] = 0;
  622.     n = CS_PLAYERSKINS + ent->number - 1;
  623.     if (cl.configstrings[n][0])
  624.     {
  625.         p = strchr(cl.configstrings[n], '\\');
  626.         if (p)
  627.         {
  628.             p += 1;
  629.             strcpy(model, p);
  630.             p = strchr(model, '/');
  631.             if (p)
  632.                 *p = 0;
  633.         }
  634.     }
  635.     // if we can't figure it out, they're male
  636.     if (!model[0])
  637.         strcpy(model, "male");
  638.  
  639.     Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", model, base+1);
  640.     mdl = R_RegisterModel(buffer);
  641.     if (!mdl) {
  642.         // not found, try default weapon model
  643.         Com_sprintf (buffer, sizeof(buffer), "players/%s/weapon.md2", model);
  644.         mdl = R_RegisterModel(buffer);
  645.         if (!mdl) {
  646.             // no, revert to the male model
  647.             Com_sprintf (buffer, sizeof(buffer), "players/%s/%s", "male", base+1);
  648.             mdl = R_RegisterModel(buffer);
  649.             if (!mdl) {
  650.                 // last try, default male weapon.md2
  651.                 Com_sprintf (buffer, sizeof(buffer), "players/male/weapon.md2");
  652.                 mdl = R_RegisterModel(buffer);
  653.             }
  654.         } 
  655.     }
  656.  
  657.     return mdl;
  658. }
  659.  
  660. // PMM - used in shell code 
  661. extern int Developer_searchpath (int who);
  662. // pmm
  663. /*
  664. ===============
  665. CL_AddPacketEntities
  666.  
  667. ===============
  668. */
  669. void CL_AddPacketEntities (frame_t *frame)
  670. {
  671.     entity_t            ent;
  672.     entity_state_t        *s1;
  673.     float                autorotate;
  674.     int                    i;
  675.     int                    pnum;
  676.     centity_t            *cent;
  677.     int                    autoanim;
  678.     clientinfo_t        *ci;
  679.     unsigned int        effects, renderfx;
  680.  
  681.     // bonus items rotate at a fixed rate
  682.     autorotate = anglemod(cl.time/10);
  683.  
  684.     // brush models can auto animate their frames
  685.     autoanim = 2*cl.time/1000;
  686.  
  687.     memset (&ent, 0, sizeof(ent));
  688.  
  689.     for (pnum = 0 ; pnum<frame->num_entities ; pnum++)
  690.     {
  691.         s1 = &cl_parse_entities[(frame->parse_entities+pnum)&(MAX_PARSE_ENTITIES-1)];
  692.  
  693.         cent = &cl_entities[s1->number];
  694.  
  695.         effects = s1->effects;
  696.         renderfx = s1->renderfx;
  697.  
  698.             // set frame
  699.         if (effects & EF_ANIM01)
  700.             ent.frame = autoanim & 1;
  701.         else if (effects & EF_ANIM23)
  702.             ent.frame = 2 + (autoanim & 1);
  703.         else if (effects & EF_ANIM_ALL)
  704.             ent.frame = autoanim;
  705.         else if (effects & EF_ANIM_ALLFAST)
  706.             ent.frame = cl.time / 100;
  707.         else
  708.             ent.frame = s1->frame;
  709.  
  710.         // quad and pent can do different things on client
  711.         if (effects & EF_PENT)
  712.         {
  713.             effects &= ~EF_PENT;
  714.             effects |= EF_COLOR_SHELL;
  715.             renderfx |= RF_SHELL_RED;
  716.         }
  717.  
  718.         if (effects & EF_QUAD)
  719.         {
  720.             effects &= ~EF_QUAD;
  721.             effects |= EF_COLOR_SHELL;
  722.             renderfx |= RF_SHELL_BLUE;
  723.         }
  724. //======
  725. // PMM
  726.         if (effects & EF_DOUBLE)
  727.         {
  728.             effects &= ~EF_DOUBLE;
  729.             effects |= EF_COLOR_SHELL;
  730.             renderfx |= RF_SHELL_DOUBLE;
  731.         }
  732.  
  733.         if (effects & EF_HALF_DAMAGE)
  734.         {
  735.             effects &= ~EF_HALF_DAMAGE;
  736.             effects |= EF_COLOR_SHELL;
  737.             renderfx |= RF_SHELL_HALF_DAM;
  738.         }
  739. // pmm
  740. //======
  741.         ent.oldframe = cent->prev.frame;
  742.         ent.backlerp = 1.0 - cl.lerpfrac;
  743.  
  744.         if (renderfx & (RF_FRAMELERP|RF_BEAM))
  745.         {    // step origin discretely, because the frames
  746.             // do the animation properly
  747.             VectorCopy (cent->current.origin, ent.origin);
  748.             VectorCopy (cent->current.old_origin, ent.oldorigin);
  749.         }
  750.         else
  751.         {    // interpolate origin
  752.             for (i=0 ; i<3 ; i++)
  753.             {
  754.                 ent.origin[i] = ent.oldorigin[i] = cent->prev.origin[i] + cl.lerpfrac * 
  755.                     (cent->current.origin[i] - cent->prev.origin[i]);
  756.             }
  757.         }
  758.  
  759.         // create a new entity
  760.     
  761.         // tweak the color of beams
  762.         if ( renderfx & RF_BEAM )
  763.         {    // the four beam colors are encoded in 32 bits of skinnum (hack)
  764.             ent.alpha = 0.30;
  765.             ent.skinnum = (s1->skinnum >> ((rand() % 4)*8)) & 0xff;
  766.             ent.model = NULL;
  767.         }
  768.         else
  769.         {
  770.             // set skin
  771.             if (s1->modelindex == 255)
  772.             {    // use custom player skin
  773.                 ent.skinnum = 0;
  774.                 ci = &cl.clientinfo[s1->skinnum & 0xff];
  775.                 ent.skin = ci->skin;
  776.                 ent.model = ci->model;
  777.                 if (!ent.skin || !ent.model)
  778.                 {
  779.                     ent.skin = cl.baseclientinfo.skin;
  780.                     ent.model = cl.baseclientinfo.model;
  781.                 }
  782.  
  783. //============
  784. //PGM
  785.                 if (renderfx & RF_USE_DISGUISE)
  786.                 {
  787.                     if(!strncmp((char *)ent.skin, "players/male", 12))
  788.                     {
  789.                         ent.skin = R_RegisterSkin ("players/male/disguise.pcx");
  790.                         ent.model = R_RegisterModel ("players/male/tris.md2");
  791.                     }
  792.                     else if(!strncmp((char *)ent.skin, "players/female", 14))
  793.                     {
  794.                         ent.skin = R_RegisterSkin ("players/female/disguise.pcx");
  795.                         ent.model = R_RegisterModel ("players/female/tris.md2");
  796.                     }
  797.                     else if(!strncmp((char *)ent.skin, "players/cyborg", 14))
  798.                     {
  799.                         ent.skin = R_RegisterSkin ("players/cyborg/disguise.pcx");
  800.                         ent.model = R_RegisterModel ("players/cyborg/tris.md2");
  801.                     }
  802.                 }
  803. //PGM
  804. //============
  805.             }
  806.             else
  807.             {
  808.                 ent.skinnum = s1->skinnum;
  809.                 ent.skin = NULL;
  810.                 ent.model = cl.model_draw[s1->modelindex];
  811.             }
  812.         }
  813.  
  814.         // only used for black hole model right now, FIXME: do better
  815.         if (renderfx == RF_TRANSLUCENT)
  816.             ent.alpha = 0.70;
  817.  
  818.         // render effects (fullbright, translucent, etc)
  819.         if ((effects & EF_COLOR_SHELL))
  820.             ent.flags = 0;    // renderfx go on color shell entity
  821.         else
  822.             ent.flags = renderfx;
  823.  
  824.         // calculate angles
  825.         if (effects & EF_ROTATE)
  826.         {    // some bonus items auto-rotate
  827.             ent.angles[0] = 0;
  828.             ent.angles[1] = autorotate;
  829.             ent.angles[2] = 0;
  830.         }
  831.         // RAFAEL
  832.         else if (effects & EF_SPINNINGLIGHTS)
  833.         {
  834.             ent.angles[0] = 0;
  835.             ent.angles[1] = anglemod(cl.time/2) + s1->angles[1];
  836.             ent.angles[2] = 180;
  837.             {
  838.                 vec3_t forward;
  839.                 vec3_t start;
  840.  
  841.                 AngleVectors (ent.angles, forward, NULL, NULL);
  842.                 VectorMA (ent.origin, 64, forward, start);
  843.                 V_AddLight (start, 100, 1, 0, 0);
  844.             }
  845.         }
  846.         else
  847.         {    // interpolate angles
  848.             float    a1, a2;
  849.  
  850.             for (i=0 ; i<3 ; i++)
  851.             {
  852.                 a1 = cent->current.angles[i];
  853.                 a2 = cent->prev.angles[i];
  854.                 ent.angles[i] = LerpAngle (a2, a1, cl.lerpfrac);
  855.             }
  856.         }
  857.  
  858.         if (s1->number == cl.playernum+1)
  859.         {
  860.             ent.flags |= RF_VIEWERMODEL;    // only draw from mirrors
  861.             // FIXME: still pass to refresh
  862.  
  863.             if (effects & EF_FLAG1)
  864.                 V_AddLight (ent.origin, 225, 1.0, 0.1, 0.1);
  865.             else if (effects & EF_FLAG2)
  866.                 V_AddLight (ent.origin, 225, 0.1, 0.1, 1.0);
  867.             else if (effects & EF_TAGTRAIL)                        //PGM
  868.                 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0);    //PGM
  869.             else if (effects & EF_TRACKERTRAIL)                    //PGM
  870.                 V_AddLight (ent.origin, 225, -1.0, -1.0, -1.0);    //PGM
  871.  
  872.             continue;
  873.         }
  874.  
  875.         // if set to invisible, skip
  876.         if (!s1->modelindex)
  877.             continue;
  878.  
  879.         if (effects & EF_BFG)
  880.         {
  881.             ent.flags |= RF_TRANSLUCENT;
  882.             ent.alpha = 0.30;
  883.         }
  884.  
  885.         // RAFAEL
  886.         if (effects & EF_PLASMA)
  887.         {
  888.             ent.flags |= RF_TRANSLUCENT;
  889.             ent.alpha = 0.6;
  890.         }
  891.  
  892.         if (effects & EF_SPHERETRANS)
  893.         {
  894.             ent.flags |= RF_TRANSLUCENT;
  895.             // PMM - *sigh*  yet more EF overloading
  896.             if (effects & EF_TRACKERTRAIL)
  897.                 ent.alpha = 0.6;
  898.             else
  899.                 ent.alpha = 0.3;
  900.         }
  901. //pmm
  902.  
  903.         // add to refresh list
  904.         V_AddEntity (&ent);
  905.  
  906.  
  907.         // color shells generate a seperate entity for the main model
  908.         if (effects & EF_COLOR_SHELL)
  909.         {
  910.             // PMM - at this point, all of the shells have been handled
  911.             // if we're in the rogue pack, set up the custom mixing, otherwise just
  912.             // keep going
  913. //            if(Developer_searchpath(2) == 2)
  914. //            {
  915.                 // all of the solo colors are fine.  we need to catch any of the combinations that look bad
  916.                 // (double & half) and turn them into the appropriate color, and make double/quad something special
  917.                 if (renderfx & RF_SHELL_HALF_DAM)
  918.                 {
  919.                     if(Developer_searchpath(2) == 2)
  920.                     {
  921.                         // ditch the half damage shell if any of red, blue, or double are on
  922.                         if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_DOUBLE))
  923.                             renderfx &= ~RF_SHELL_HALF_DAM;
  924.                     }
  925.                 }
  926.  
  927.                 if (renderfx & RF_SHELL_DOUBLE)
  928.                 {
  929.                     if(Developer_searchpath(2) == 2)
  930.                     {
  931.                         // lose the yellow shell if we have a red, blue, or green shell
  932.                         if (renderfx & (RF_SHELL_RED|RF_SHELL_BLUE|RF_SHELL_GREEN))
  933.                             renderfx &= ~RF_SHELL_DOUBLE;
  934.                         // if we have a red shell, turn it to purple by adding blue
  935.                         if (renderfx & RF_SHELL_RED)
  936.                             renderfx |= RF_SHELL_BLUE;
  937.                         // if we have a blue shell (and not a red shell), turn it to cyan by adding green
  938.                         else if (renderfx & RF_SHELL_BLUE)
  939.                             // go to green if it's on already, otherwise do cyan (flash green)
  940.                             if (renderfx & RF_SHELL_GREEN)
  941.                                 renderfx &= ~RF_SHELL_BLUE;
  942.                             else
  943.                                 renderfx |= RF_SHELL_GREEN;
  944.                     }
  945.                 }
  946. //            }
  947.             // pmm
  948.             ent.flags = renderfx | RF_TRANSLUCENT;
  949.             ent.alpha = 0.30;
  950.             V_AddEntity (&ent);
  951.         }
  952.  
  953.         ent.skin = NULL;        // never use a custom skin on others
  954.         ent.skinnum = 0;
  955.         ent.flags = 0;
  956.         ent.alpha = 0;
  957.  
  958.         // duplicate for linked models
  959.         
  960.         if (s1->modelindex2)
  961.         {
  962.             if (s1->modelindex2 == 255)
  963.             {    // custom weapon
  964.                 ci = &cl.clientinfo[s1->skinnum & 0xff];
  965.                 i = (s1->skinnum >> 8); // 0 is default weapon model
  966.                 if (!cl_vwep->value || i > MAX_CLIENTWEAPONMODELS - 1)
  967.                     i = 0;
  968.                 ent.model = ci->weaponmodel[i];
  969.                 if (!ent.model) {
  970.                     if (i != 0)
  971.                         ent.model = ci->weaponmodel[0];
  972.                     if (!ent.model)
  973.                         ent.model = cl.baseclientinfo.weaponmodel[0];
  974.                 }
  975.             }
  976.             else
  977.                 ent.model = cl.model_draw[s1->modelindex2];
  978.  
  979.             // PMM - check for the defender sphere shell .. make it translucent
  980.             // replaces the previous version which used the high bit on modelindex2 to determine transparency
  981.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/items/shell/tris.md2"))
  982.             {
  983.                 ent.alpha = 0.32;
  984.                 ent.flags = RF_TRANSLUCENT;
  985.             }
  986.             // pmm
  987.  
  988.             //here is where we will set the alpha for the linked model for the martian helmet
  989.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/monsters/hi_res/martian_helmet/tris.md2"))
  990.             { 
  991.                 ent.alpha = 0.4;
  992.                 ent.flags = RF_TRANSLUCENT;
  993.             }
  994.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/monsters/helmet/tris2.md2"))
  995.             {
  996.                 ent.alpha = 0.4;
  997.                 ent.flags = RF_TRANSLUCENT;
  998.             }
  999.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/npc/helmet/tris.md2"))
  1000.             {
  1001.                 ent.alpha = 0.4;
  1002.                 ent.flags = RF_TRANSLUCENT;
  1003.             }
  1004.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex2)], "models/monsters/robot_top/tris.md2"))
  1005.             {
  1006.                 ent.alpha = 0.4;
  1007.                 ent.flags = RF_TRANSLUCENT;
  1008.             }
  1009.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex)], "models/objects/blank/tris.md2"))
  1010.             {
  1011.                 ent.alpha = 0.1;
  1012.                 ent.flags = RF_TRANSLUCENT;
  1013.             }
  1014.             
  1015.             V_AddEntity (&ent);
  1016.  
  1017.             //PGM - make sure these get reset.
  1018.             ent.flags = 0;
  1019.             ent.alpha = 0;
  1020.             //PGM
  1021.         }
  1022.         if (s1->modelindex3)
  1023.         {
  1024.             ent.model = cl.model_draw[s1->modelindex3];
  1025.             if (!Q_strcasecmp (cl.configstrings[CS_MODELS+(s1->modelindex3)], "players/martian/helmet.md2"))
  1026.             {
  1027.                 ent.alpha = 0.4;
  1028.                 ent.flags = RF_TRANSLUCENT;
  1029.             }
  1030.             V_AddEntity (&ent);
  1031.         }
  1032.         if (s1->modelindex4)
  1033.         {
  1034.             ent.model = cl.model_draw[s1->modelindex4];
  1035.             V_AddEntity (&ent);
  1036.         }
  1037.  
  1038.         if ( effects & EF_POWERSCREEN )
  1039.         {
  1040.             ent.model = cl_mod_powerscreen;
  1041.             ent.oldframe = 0;
  1042.             ent.frame = 0;
  1043.             ent.flags |= (RF_TRANSLUCENT | RF_SHELL_GREEN);
  1044.             ent.alpha = 0.30;
  1045.             V_AddEntity (&ent);
  1046.         }
  1047.  
  1048.         // add automatic particle trails
  1049.         if ( (effects&~EF_ROTATE) )
  1050.         {
  1051.             if (effects & EF_ROCKET)
  1052.             {
  1053.                 CL_RocketTrail (cent->lerp_origin, ent.origin, cent);
  1054.                 V_AddLight (ent.origin, 200, 1, 1, 0);
  1055.             }
  1056.             if (effects & EF_SHIPEXHAUST)
  1057.             {
  1058.                 CL_ShipExhaust (cent->lerp_origin, ent.origin, cent);
  1059.                 V_AddLight (ent.origin, 200, 1, 1, 0);
  1060.             }
  1061.             // PGM - Do not reorder EF_BLASTER and EF_HYPERBLASTER. 
  1062.             // EF_BLASTER | EF_TRACKER is a special case for EF_BLASTER2... Cheese!
  1063.             else if (effects & EF_BLASTER)
  1064.             {
  1065. //                CL_BlasterTrail (cent->lerp_origin, ent.origin);
  1066. //PGM
  1067.                 if (effects & EF_TRACKER)    // lame... problematic?
  1068.                 {
  1069.                     CL_BlasterTrail2 (cent->lerp_origin, ent.origin);
  1070.                     V_AddLight (ent.origin, 200, 0, 1, 0);        
  1071.                 }
  1072.                 else
  1073.                 {
  1074.                     CL_BlasterTrail (cent->lerp_origin, ent.origin);
  1075.                     V_AddLight (ent.origin, 200, 1, 1, 0);
  1076.                 }
  1077. //PGM
  1078.             }
  1079.             else if (effects & EF_HYPERBLASTER)
  1080.             {
  1081.                 if (effects & EF_TRACKER)                        // PGM    overloaded for blaster2.
  1082.                     V_AddLight (ent.origin, 200, 0, 1, 0);        // PGM
  1083.                 else                                            // PGM
  1084.                     V_AddLight (ent.origin, 200, 1, 1, 0);
  1085.             }
  1086.             else if (effects & EF_GIB)
  1087.             {
  1088.                 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
  1089.             }
  1090.             else if (effects & EF_GRENADE)
  1091.             {
  1092.                 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);
  1093.             }
  1094.             else if (effects & EF_FLIES)
  1095.             {
  1096.                 CL_FlyEffect (cent, ent.origin);
  1097.             }
  1098.             else if (effects & EF_BFG)
  1099.             {
  1100.                 static int bfg_lightramp[6] = {300, 400, 600, 300, 150, 75};
  1101.  
  1102.                 if (effects & EF_ANIM_ALLFAST)
  1103.                 {
  1104.                     CL_BfgParticles (&ent);
  1105.                     i = 200;
  1106.                 }
  1107.                 else
  1108.                 {
  1109.                     i = bfg_lightramp[s1->frame];
  1110.                 }
  1111.                 V_AddLight (ent.origin, i, 0, 1, 0);
  1112.             }
  1113.             else if (effects & EF_FLAG1)
  1114.             {
  1115.                 CL_FlagTrail (cent->lerp_origin, ent.origin, 242);
  1116.                 V_AddLight (ent.origin, 225, 1, 0.1, 0.1);
  1117.             }
  1118.             else if (effects & EF_FLAG2)
  1119.             {
  1120.                 CL_FlagTrail (cent->lerp_origin, ent.origin, 115);
  1121.                 V_AddLight (ent.origin, 225, 0.1, 0.1, 1);
  1122.             }
  1123. //======
  1124. //ROGUE
  1125.             else if (effects & EF_TAGTRAIL)
  1126.             {
  1127.                 CL_TagTrail (cent->lerp_origin, ent.origin, 220);
  1128.                 V_AddLight (ent.origin, 225, 1.0, 1.0, 0.0);
  1129.             }
  1130.             else if (effects & EF_TRACKERTRAIL)
  1131.             {
  1132.                 if (effects & EF_TRACKER)
  1133.                 {
  1134.                     float intensity;
  1135.  
  1136.                     intensity = 50 + (500 * (sin(cl.time/500.0) + 1.0));
  1137.                     // FIXME - check out this effect in rendition
  1138.                     V_AddLight (ent.origin, intensity, -1.0, -1.0, -1.0);
  1139.                 }
  1140.                 else
  1141.                 {
  1142.                     CL_Tracker_Shell (cent->lerp_origin);
  1143.                     V_AddLight (ent.origin, 155, -1.0, -1.0, -1.0);
  1144.                 }
  1145.             }
  1146.             else if (effects & EF_TRACKER)
  1147.             {
  1148.                 CL_TrackerTrail (cent->lerp_origin, ent.origin, 0);
  1149.                 // FIXME - check out this effect in rendition
  1150.                 V_AddLight (ent.origin, 200, -1, -1, -1);
  1151.             }
  1152. //ROGUE
  1153. //======
  1154.             // RAFAEL
  1155.             else if (effects & EF_GREENGIB)
  1156.             {
  1157.                 CL_DiminishingTrail (cent->lerp_origin, ent.origin, cent, effects);                
  1158.             }
  1159.             // RAFAEL
  1160.             else if (effects & EF_IONRIPPER)
  1161.             {
  1162.                 CL_IonripperTrail (cent->lerp_origin, ent.origin);
  1163.                 V_AddLight (ent.origin, 100, 1, 0.5, 0.5);
  1164.             }
  1165.             // RAFAEL
  1166.             else if (effects & EF_BLUEHYPERBLASTER)
  1167.             {
  1168.                 V_AddLight (ent.origin, 200, 0, 0, 1);
  1169.             }
  1170.             // RAFAEL
  1171.             else if (effects & EF_PLASMA)
  1172.             {
  1173.                 if (effects & EF_ANIM_ALLFAST)
  1174.                 {
  1175.                     CL_BlasterTrail (cent->lerp_origin, ent.origin);
  1176.                 }
  1177.                 V_AddLight (ent.origin, 130, 1, 0.5, 0.5);
  1178.             }
  1179.         }
  1180.  
  1181.         VectorCopy (ent.origin, cent->lerp_origin);
  1182.     }
  1183. }
  1184.  
  1185.  
  1186.  
  1187. /*
  1188. ==============
  1189. CL_AddViewWeapon
  1190. ==============
  1191. */
  1192. void CL_AddViewWeapon (player_state_t *ps, player_state_t *ops)
  1193. {
  1194.     entity_t    gun;        // view model
  1195.     int            i;
  1196.  
  1197.     // allow the gun to be completely removed
  1198.     if (!cl_gun->value)
  1199.         return;
  1200.  
  1201.     // don't draw gun if in wide angle view
  1202.     if (ps->fov > 90)
  1203.         return;
  1204.  
  1205.     memset (&gun, 0, sizeof(gun));
  1206.  
  1207.     if (gun_model)
  1208.         gun.model = gun_model;    // development tool
  1209.     else
  1210.         gun.model = cl.model_draw[ps->gunindex];
  1211.     if (!gun.model)
  1212.         return;
  1213.  
  1214.     // set up gun position
  1215.     for (i=0 ; i<3 ; i++)
  1216.     {
  1217.         gun.origin[i] = cl.refdef.vieworg[i] + ops->gunoffset[i]
  1218.             + cl.lerpfrac * (ps->gunoffset[i] - ops->gunoffset[i]);
  1219.         gun.angles[i] = cl.refdef.viewangles[i] + LerpAngle (ops->gunangles[i],
  1220.             ps->gunangles[i], cl.lerpfrac);
  1221.     }
  1222.  
  1223.     if (gun_frame)
  1224.     {
  1225.         gun.frame = gun_frame;    // development tool
  1226.         gun.oldframe = gun_frame;    // development tool
  1227.     }
  1228.     else
  1229.     {
  1230.         gun.frame = ps->gunframe;
  1231.         if (gun.frame == 0)
  1232.             gun.oldframe = 0;    // just changed weapons, don't lerp from old
  1233.         else
  1234.             gun.oldframe = ops->gunframe;
  1235.     }
  1236.  
  1237.     gun.flags = RF_MINLIGHT | RF_DEPTHHACK | RF_WEAPONMODEL;
  1238.     gun.backlerp = 1.0 - cl.lerpfrac;
  1239.     VectorCopy (gun.origin, gun.oldorigin);    // don't lerp at all
  1240.     V_AddEntity (&gun);
  1241. }
  1242.  
  1243.  
  1244. /*
  1245. ===============
  1246. CL_CalcViewValues
  1247.  
  1248. Sets cl.refdef view values
  1249. ===============
  1250. */
  1251. void CL_CalcViewValues (void)
  1252. {
  1253.     int            i;
  1254.     float        lerp, backlerp;
  1255.     centity_t    *ent;
  1256.     frame_t        *oldframe;
  1257.     player_state_t    *ps, *ops;
  1258.  
  1259.     // find the previous frame to interpolate from
  1260.     ps = &cl.frame.playerstate;
  1261.     i = (cl.frame.serverframe - 1) & UPDATE_MASK;
  1262.     oldframe = &cl.frames[i];
  1263.     if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
  1264.         oldframe = &cl.frame;        // previous frame was dropped or involid
  1265.     ops = &oldframe->playerstate;
  1266.  
  1267.     // see if the player entity was teleported this frame
  1268.     if ( fabs(ops->pmove.origin[0] - ps->pmove.origin[0]) > 256*8
  1269.         || abs(ops->pmove.origin[1] - ps->pmove.origin[1]) > 256*8
  1270.         || abs(ops->pmove.origin[2] - ps->pmove.origin[2]) > 256*8)
  1271.         ops = ps;        // don't interpolate
  1272.  
  1273.     ent = &cl_entities[cl.playernum+1];
  1274.     lerp = cl.lerpfrac;
  1275.  
  1276.     // calculate the origin
  1277.     if ((cl_predict->value) && !(cl.frame.playerstate.pmove.pm_flags & PMF_NO_PREDICTION))
  1278.     {    // use predicted values
  1279.         unsigned    delta;
  1280.  
  1281.         backlerp = 1.0 - lerp;
  1282.         for (i=0 ; i<3 ; i++)
  1283.         {
  1284.             cl.refdef.vieworg[i] = cl.predicted_origin[i] + ops->viewoffset[i] 
  1285.                 + cl.lerpfrac * (ps->viewoffset[i] - ops->viewoffset[i])
  1286.                 - backlerp * cl.prediction_error[i];
  1287.         }
  1288.  
  1289.         // smooth out stair climbing
  1290.         delta = cls.realtime - cl.predicted_step_time;
  1291.         if (delta < 100)
  1292.             cl.refdef.vieworg[2] -= cl.predicted_step * (100 - delta) * 0.01;
  1293.     }
  1294.     else
  1295.     {    // just use interpolated values
  1296.         for (i=0 ; i<3 ; i++)
  1297.             cl.refdef.vieworg[i] = ops->pmove.origin[i]*0.125 + ops->viewoffset[i] 
  1298.                 + lerp * (ps->pmove.origin[i]*0.125 + ps->viewoffset[i] 
  1299.                 - (ops->pmove.origin[i]*0.125 + ops->viewoffset[i]) );
  1300.     }
  1301.  
  1302.     // if not running a demo or on a locked frame, add the local angle movement
  1303.     if ( cl.frame.playerstate.pmove.pm_type < PM_DEAD )
  1304.     {    // use predicted values
  1305.         for (i=0 ; i<3 ; i++)
  1306.             cl.refdef.viewangles[i] = cl.predicted_angles[i];
  1307.     }
  1308.     else
  1309.     {    // just use interpolated values
  1310.         for (i=0 ; i<3 ; i++)
  1311.             cl.refdef.viewangles[i] = LerpAngle (ops->viewangles[i], ps->viewangles[i], lerp);
  1312.     }
  1313.  
  1314.     for (i=0 ; i<3 ; i++)
  1315.         cl.refdef.viewangles[i] += LerpAngle (ops->kick_angles[i], ps->kick_angles[i], lerp);
  1316.  
  1317.     AngleVectors (cl.refdef.viewangles, cl.v_forward, cl.v_right, cl.v_up);
  1318.  
  1319.     // interpolate field of view
  1320.     cl.refdef.fov_x = ops->fov + lerp * (ps->fov - ops->fov);
  1321.  
  1322.     // don't interpolate blend color
  1323.     for (i=0 ; i<4 ; i++)
  1324.         cl.refdef.blend[i] = ps->blend[i];
  1325.  
  1326.     // add the weapon
  1327.     CL_AddViewWeapon (ps, ops);
  1328. }
  1329.  
  1330. /*
  1331. ===============
  1332. CL_AddEntities
  1333.  
  1334. Emits all entities, particles, and lights to the refresh
  1335. ===============
  1336. */
  1337. void CL_AddEntities (void)
  1338. {
  1339.     if (cls.state != ca_active)
  1340.         return;
  1341.  
  1342.     if (cl.time > cl.frame.servertime)
  1343.     {
  1344.         if (cl_showclamp->value)
  1345.             Com_Printf ("high clamp %i\n", cl.time - cl.frame.servertime);
  1346.         cl.time = cl.frame.servertime;
  1347.         cl.lerpfrac = 1.0;
  1348.     }
  1349.     else if (cl.time < cl.frame.servertime - 100)
  1350.     {
  1351.         if (cl_showclamp->value)
  1352.             Com_Printf ("low clamp %i\n", cl.frame.servertime-100 - cl.time);
  1353.         cl.time = cl.frame.servertime - 100;
  1354.         cl.lerpfrac = 0;
  1355.     }
  1356.     else
  1357.         cl.lerpfrac = 1.0 - (cl.frame.servertime - cl.time) * 0.01;
  1358.  
  1359.     if (cl_timedemo->value)
  1360.         cl.lerpfrac = 1.0;
  1361.  
  1362. //    CL_AddPacketEntities (&cl.frame);
  1363. //    CL_AddTEnts ();
  1364. //    CL_AddParticles ();
  1365. //    CL_AddDLights ();
  1366. //    CL_AddLightStyles ();
  1367.  
  1368.     CL_CalcViewValues ();
  1369.  
  1370.     // PMM - moved this here so the heat beam has the right values for the vieworg, and can lock the beam to the gun
  1371.     CL_AddPacketEntities (&cl.frame);
  1372.     CL_AddTEnts ();
  1373.     CL_AddParticles ();
  1374.     CL_AddDLights ();
  1375.     CL_AddLightStyles ();
  1376. }
  1377.  
  1378.  
  1379.  
  1380. /*
  1381. ===============
  1382. CL_GetEntitySoundOrigin
  1383.  
  1384. Called to get the sound spatialization origin
  1385. ===============
  1386. */
  1387. void CL_GetEntitySoundOrigin (int ent, vec3_t org)
  1388. {
  1389.     centity_t    *old;
  1390.  
  1391.     if (ent < 0 || ent >= MAX_EDICTS)
  1392.         Com_Error (ERR_DROP, "CL_GetEntitySoundOrigin: bad ent");
  1393.     old = &cl_entities[ent];
  1394.     VectorCopy (old->lerp_origin, org);
  1395.  
  1396.     // FIXME: bmodel issues...
  1397. }
  1398.